package aparapi;

import com.aparapi.Kernel;
import ex.DiffSetPair;
import org.apache.commons.math3.util.CombinatoricsUtils;

import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;

/**
 * @Description 用来判断单个的差集偶的核函数
 * @Date 2022/3/25 22:39
 * @Author eric ling
 */
public class DspKernel extends Kernel {
    // global变量 基本数据类型的数组默认为global内存区域
    public final byte[] k1SetAllComb;
    public final byte[] k2SetAllComb;
    public boolean[] validComb;

    public byte[] occurrence;

    // constant
    @Constant
    public final byte[] diffTabIdxInK1Set;
    @Constant
    public final byte[] diffTabIdxInK2Set;

    // system variable
    @Constant
    public final int v;
    @Constant
    public final int k1;
    @Constant
    public final int k2;
    @Constant
    public final int e;
    @Constant
    public final int lambda;
    @Constant
    public final int combCount;
    @Constant
    public final int passCount;

    public DspKernel(byte[] k1SetAllComb, byte[] k2SetAllComb, DiffSetPair pair, int combCount) {
        this.k1SetAllComb = k1SetAllComb;
        this.k2SetAllComb = k2SetAllComb;

        this.v = pair.getV();
        this.k1 = pair.getK1();
        this.k2 = pair.getK2();
        this.e = pair.getE();
        this.lambda = pair.getLambda();
        this.passCount = this.k1 * this.k2 + this.v;

        this.combCount = combCount;
        System.out.println(combCount + "种组合正在验证.");
        validComb = new boolean[combCount];
        this.occurrence = new byte[combCount * v];

        diffTabIdxInK1Set = new byte[this.k1 * this.k2];
        diffTabIdxInK2Set = new byte[this.k1 * this.k2];
        int tmpIdx = 0;
        for (byte i = 0; i < k1; i++) {
            for (byte j = 0; j < k2; j++) {
                diffTabIdxInK1Set[tmpIdx] = i;
                diffTabIdxInK2Set[tmpIdx] = j;
                tmpIdx++;
            }
        }
    }

    @Override
    public void run() {
        int globalId = getGlobalId();
        int passId = getPassId();
        if (passId < k1 * k2) {
            // 构造差表
            int diff = k1SetAllComb[globalId * k1 + diffTabIdxInK1Set[passId]] - k2SetAllComb[globalId * k2 + diffTabIdxInK2Set[passId]];
            diff = (diff + v);
            diff = diff % v;
            occurrence[globalId * v + diff]++;

        }
        if (passId >= k1 * k2 && passId != (passCount - 1)) {
            // 遍历差表
            if (occurrence[globalId * v + passId - k1 * k2 + 1] != lambda) {
                occurrence[globalId * v] = -1;
            }

        }

        if (passId == (passCount - 1)) {
            // 判断是否为差集偶
            if (occurrence[globalId * v] != -1) {
                validComb[globalId] = true;
            }
        }
    }

    public int save(Writer writer) throws IOException {
        int found = 0;

        // 将合法的差集偶保存到文件中
        for (int i = 0; i < validComb.length; i++) {
            if (validComb[i]) {
                found++;
                // 将当前组合元素取出
//                 System.out.print("D1=" + Arrays.toString(Arrays.copyOfRange(k1SetAllComb, i * k1, i * k1 + k1)));
//                 System.out.println(", D2=" + Arrays.toString(Arrays.copyOfRange(k2SetAllComb, i * k2, i * k2 + k2)));
                writer.write("D1=" + Arrays.toString(Arrays.copyOfRange(k1SetAllComb, i * k1, i * k1 + k1)) + ", D2=" + Arrays.toString(Arrays.copyOfRange(k2SetAllComb, i * k2, i * k2 + k2)) + "\n");
            }
        }
        return found;
    }

}
